/**
 * \class CompoundContext Generator/context/CompoundContext.h
 *
 *  \brief Compund context
 *
 *  The compound context works in the clause context. that
 *  is for example a if statement see below.
 *
 * \code
 * <env context>
 *  if( <expr context> )
 *  {
 *    <compound context>
 *    var = <expr context>
 *  }
 * \endcode
 *
 * 	The variable var is either part of the env context if its defined before the
 * 	if statement, or it is part of the compound context. This due to the fact that
 * 	its instantiated before it is declared with an expression. If it were to be instantiated
 * 	where it was declared it would become part of the compound context.
 *
 *  @see IContext
 *  @see IContextDecorator
 *  Created on: 15 apr 2011
 *      Author: ytc0039
 *
 *  \ingroup Context
 */

#ifndef COMPOUNDCONTEXT_H_
#define COMPOUNDCONTEXT_H_

#include <Generator/context/IContextDecorator.h>
#include <Generator/context/IContext.h>

class CompoundContext: public IContextDecorator {
public:
	CompoundContext(IContext *context);
	virtual ~CompoundContext();

	/**
	 * \brief Check for identification.
	 *
	 * Check for identification in the CompoundContext.
	 *
	 * @param ident
	 * @return true if exists.
	 */
	virtual bool identExists(const Ident& ident) const;

	/**
	 * \brief Add a identifier and its type to this context
	 *
	 * Add a type and identifier to a compound context.
	 * Addition to the context can only be done if the ident does not
	 * exists in any of the parent contexts.
	 * true is return if successfully added.
	 *
	 * @param type
	 * @param ident
	 * @return true if add was successful.
	 */

	virtual bool addIdent(TypeEnum type, const Ident& ident);

	/**
	 * \brief remove an identifier from context.
	 *
	 * Remove a identifier variable from the context.
	 * The remove will be active both on this context and the parent context.
	 * The remove will start on the parent context and then try this context.
	 * If successful on any parent or this context, the return value will be true.
	 * It should not be possible to have same key on two contexts, but its not checked here.
	 *
	 *
	 * @param ident
	 * @return true if successfully removed
	 */
	virtual bool removeIdent(const Ident& ident);

	/**
	 * \brief Check for a identifier and return type
	 *
	 * Return the type for a identifier, if the identifier don't exists
	 * the return value is false. If found the type will be placed in the
	 * type reference
	 *
	 * @see TypeEnum
	 *
	 * @param ident
	 * @param[in/out] type - if found the type will be of t
	 * @return true if found
	 */
	virtual bool findType(const Ident& ident,TypeEnum& type)const;
	/**
	 * \brief Implementation of getAllOfType from IContext.
	 *
	 * Checks all occurrences of type in the Context.
	 *
	 * @see IContext
	 *
	 * @param type to be checked
	 * @param list with matching idents.
	 */
	virtual void getAllOfType(TypeEnum type, IContext::TypeList& list) const;

private:
	CONTEXT_MAP m_context;
};

#endif /* COMPOUNDCONTEXT_H_ */
